#include "ftgraph.h"
#include "ftcontrols.h"

#define PEN_TITLE QPen( QColor("red"), 2)
#define PEN_DATA QPen( QColor("white"), 0)

FTGraph::FTGraph(QWidget *parent) :
    QWidget(parent)
{
    image = NULL;
    x_title = y_title = "";
    x_min = x_max = y_min = y_max = y_center = x_center = 0.0;
    x_flags = y_flags = FTGraph::none;
}

FTGraph::~FTGraph()
{
    if ( image != NULL )
        delete image;
}

void FTGraph::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
//    updateGraph();
    if ( image != NULL )
        painter.drawImage( rect(), *image, image->rect() );
    else
        painter.drawText( rect(), tr("Data not set") );
    painter.drawRect( rect().adjusted( 1, 1, -1, -1) );
}

void FTGraph::resizeEvent(QResizeEvent *)
{
    updateGraph();
}

void FTGraph::setXaxis( const QString& title,
                        FTGraph::axis_flags flag,
                        double center,
                        double min,
                        double max)
{
    x_title = title;
    x_min = min;
    x_max = max;
    x_center = center;
    x_flags = flag;
}

void FTGraph::setYaxis( const QString& title,
                        FTGraph::axis_flags flag,
                        double center,
                        double min,
                        double max)
{
    y_title = title;
    y_min = min;
    y_max = max;
    y_center = center;
    y_flags = flag;
}

void FTGraph::setData( const QVector<QPointF>& pts)
{
    points = pts;
    updateGraph();
}

void FTGraph::setTitle(const QString & t)
{
    title = t;
}

void FTGraph::updateGraph()
{
    // First, fix the axis if not already defined
    if ( y_min >= y_max )
        autoYaxis();
    if ( x_min >= x_max )
        autoXaxis();

    if ( image != NULL )
        delete image;

    int widget_width = width();
    int widget_height = height();
    QRect widget_rect = rect();

    // Build and clear the image
    image = new QImage( widget_width, widget_height, QImage::Format_RGB16 );
    image->fill(0);
    QPainter painter(image);
    painter.setFont( FTControls::font( FTControls::FontSmall ));

    // Get some measurements of stuff which is required
    QRectF x_title_rect = painter.boundingRect(widget_rect, x_title );
    QRectF y_title_rect = painter.boundingRect(widget_rect, y_title );
    int border = x_title_rect.height();
    double graph_width = (x_max - x_min);
    double graph_height = (y_max - y_min);

    // Scale/translate the image to fit the requested x,y axis scale
    painter.save();
    painter.setPen( PEN_DATA );
    double scale_x = (widget_width-border*2) / graph_width;
    double scale_y = (widget_height-border*2) / graph_height;
    painter.scale( scale_x, -scale_y );
    painter.translate( -(double)x_min + (double)border/scale_x,
                       -(double)y_max - (double)border/scale_y );
    // Draw the lines!
    painter.drawPolyline( points );
    painter.restore();

    // Now, to the "other" stuff...
    painter.setPen( PEN_TITLE );

    // Draw the title (centered on top):
    if ( title != "" )
    {
        QRect title_rect = rect();
        title_rect.setHeight( title_rect.height() / 2);
        painter.drawText( title_rect, title );
    }

    // Draw the axis
    QLineF xAxis( 0, widget_height-border, widget_width-border, widget_height-border );
    painter.drawLine(xAxis);
    x_title_rect.moveTo( (widget_width - x_title_rect.width()) / 2,
                         widget_height - x_title_rect.height() );
    painter.drawText( x_title_rect, x_title );
    QString x_min_str;
    QString x_max_str;
    if ( x_flags == FTGraph::is_time )
    {
        x_min_str = QDateTime::fromTime_t( x_min ).toString("dd/MM/yy,hh:mm:ss");
        x_max_str = QDateTime::fromTime_t( x_max ).toString("dd/MM/yy,hh:mm:ss");
    }
    else
    {
        x_min_str = QString("%1").arg( x_min );
        x_max_str = QString("%1").arg( x_max );
    }
    QRectF tmp_rect = painter.boundingRect( widget_rect, x_min_str );
    tmp_rect.moveTo( border, widget_height-border);
    painter.drawText( tmp_rect, x_min_str );

    tmp_rect = painter.boundingRect( widget_rect, x_max_str );
    tmp_rect.moveTo( widget_width-border-tmp_rect.width(), widget_height-border);
    painter.drawText( tmp_rect, x_max_str );

    QLineF yAxis( border, border, border, widget_height );
    painter.drawLine(yAxis);

    painter.rotate( -90.0 );
    painter.translate( -widget_height, 0 );
    y_title_rect.moveTo((widget_height - y_title_rect.width())/2 ,0 );
    painter.drawText( y_title_rect, y_title );

    QString y_min_str;
    QString y_max_str;
    if ( y_flags == FTGraph::is_time )
    {
        y_min_str = QDateTime::fromTime_t( y_min ).toString("dd/MM/yy,hh:mm:ss");
        y_max_str = QDateTime::fromTime_t( y_max ).toString("dd/MM/yy,hh:mm:ss");
    }
    else
    {
        y_min_str = QString("%1").arg( y_min );
        y_max_str = QString("%1").arg( y_max );
    }
    tmp_rect = painter.boundingRect( widget_rect, y_min_str );
    tmp_rect.moveTo( border+2, 0);
    painter.drawText( tmp_rect, y_min_str );

    tmp_rect = painter.boundingRect( widget_rect, y_max_str );
    tmp_rect.moveTo( widget_height-border-tmp_rect.width(), 0);
    painter.drawText( tmp_rect, y_max_str );

    update();
}

void FTGraph::autoXaxis()
{
    bool min_found = false;
    bool max_found = false;
    foreach (const QPointF& pt, points )
    {
        if ( !min_found )
        {
            min_found = true;
            x_min = pt.x();
        }
        else if (pt.x() < x_min)
        {
            x_min = pt.x();
        }
        if ( !max_found )
        {
            max_found = true;
            x_max = pt.x();
        }
        else if (pt.x() > x_max)
        {
            x_max = pt.x();
        }
    }
}

void FTGraph::autoYaxis()
{
    bool min_found = false;
    bool max_found = false;
    foreach (const QPointF& pt, points )
    {
        if ( !min_found )
        {
            min_found = true;
            y_min = pt.y();
        }
        else if (pt.y() < y_min)
        {
            y_min = pt.y();
        }
        if ( !max_found )
        {
            max_found = true;
            y_max = pt.y();
        }
        else if (pt.y() > y_max)
        {
            y_max = pt.y();
        }
    }
}
